package com.tbit.main.controller;

import cn.hutool.core.collection.CollUtil;
import com.tbit.common.entity.pojo.dto.OperatingMapMainDTO;
import com.tbit.common.entity.pojo.vo.OperatingMonitorMainVO;
import com.tbit.main.common.JsonResult;
import com.tbit.common.constant.MethodEnum;
import com.tbit.common.constant.ModuleEnum;
import com.tbit.main.constant.OperateLog;
import com.tbit.main.constant.SysConstant;
import com.tbit.main.exception.BaseException;
import com.tbit.main.pojo.*;
import com.tbit.main.service.*;
import com.tbit.main.util.Assert;
import com.tbit.main.util.DateTimeUtil;
import com.tbit.manager.api.MachineApi;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.validation.constraints.NotNull;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

/**
 * 设备管理
 *
 * @author Leon
 * 2019年11月11日 下午1:37:42
 */
@RestController
@RequestMapping("/machineManager")
public class MachineManagerController {
    @Autowired
    private MachineManagerService machineManagerService;
    @Autowired
    private RedisService redisService;
    @Autowired
    private AccountUserService accountUserService;
    @Autowired
    private TokenService tokenService;
    @Autowired
    private GeoreGionService georeGionService;
    @Autowired
    private MachineApi machineApi;

    /**
     * 查询所有设备
     */
    @RequestMapping("/getAll")
    public JsonResult<List<MachineStatusBorrow>> getAll(String token, Integer accountId, Integer mapType,
                             @RequestParam(value = "regionId", required = false) List<Integer> regionId) {
        AccountUser accountUserToken = tokenService.getAccount(token);
        Assert.notNull(accountId, "AccountUser.agentId.notNull");
        if (mapType == null) {
            mapType = SysConstant.GOOGLE;
        }

        if (CollUtil.isEmpty(regionId)) {
            regionId = georeGionService.getByAccountUserId(accountUserToken.getAccountUserId());
        }

        List<MachineStatusBorrow> machineStatusBorrows = machineManagerService.getAll(accountUserToken, accountId, mapType, regionId);

        return JsonResult.succ(machineStatusBorrows);
    }


    /**
     * 条件查询所有记录
     *
     * @param token
     * @param machineStateData
     * @return
     */
    @RequestMapping("/getByKey")
    public JsonResult getByKey(String token, MachineStateData machineStateData) {
        AccountUser accountUserToken = tokenService.getAccount(token);
        Assert.notNull(machineStateData.getAccountId(), "AccountUser.agentId.notNull");
        Integer mapType = machineStateData.getMapType();
        if (mapType == null) {
            mapType = SysConstant.GOOGLE;
        }

        if (machineStateData.getRegionId() == null || machineStateData.getRegionId().size() == 0) {
            machineStateData.setRegionId(georeGionService.getByAccountUserId(accountUserToken.getAccountUserId()));
        }
        MachineManagerResult machineManagerResult = new MachineManagerResult();
        List<String> existNOs = new ArrayList<>();
        /**换电车辆*/
        if (machineStateData.getPower() == 1) {
            List<MachineStatus> power = machineManagerService.getByPower(accountUserToken,
                    machineStateData.getAccountId(), null, mapType, machineStateData.getRegionId(), machineStateData.getStartSoc(), machineStateData.getEndSoc());
            List<MachineStatus> result = new ArrayList<>();
            power.forEach(machineStatus -> {
                if (!existNOs.contains(machineStatus.getMachineNO())) {
                    existNOs.add(machineStatus.getMachineNO());
                    result.add(machineStatus);
                }
            });
            machineManagerResult.setPower(result);
        }
        /**闲置车辆*/
        if (machineStateData.getNoUse() == 1) {
            List<MachineStatusBorrow> noUse = machineManagerService.getByUnuse(accountUserToken, machineStateData.getAccountId()
                    , null, mapType, machineStateData.getRegionId(), machineStateData.getStart(), machineStateData.getEnd());
            List<MachineStatusBorrow> result = new ArrayList<>();
            noUse.forEach(machineStatus -> {
                if (!existNOs.contains(machineStatus.getMachineNO())) {
                    existNOs.add(machineStatus.getMachineNO());
                    result.add(machineStatus);
                }
            });
            machineManagerResult.setNoUse(result);
        }
        /**故障车辆*/
        if (machineStateData.getFault() == 1) {
            List<MachineStatusFault> faults = machineManagerService.getByFault(accountUserToken,
                    machineStateData.getAccountId(), mapType, null, machineStateData.getRegionId());
            List<MachineStatusFault> result = new ArrayList<>();
            faults.forEach(machineStatusFault -> {
                if (!existNOs.contains(machineStatusFault.getMachineNO())) {
                    existNOs.add(machineStatusFault.getMachineNO());
                    result.add(machineStatusFault);
                }
            });
            machineManagerResult.setFault(result);
        }
        /**异常车辆*/
        if (machineStateData.getAbnormal() == 1) {
            List<MachineStatusAbnormal> abnormales = machineManagerService.getByAbnormal(accountUserToken,
                    machineStateData.getAccountId(), machineStateData.getAbnormalType(), mapType, machineStateData.getRegionId()
                    , machineStateData.getHours());
            List<MachineStatusAbnormal> result = new ArrayList<>();
            abnormales.forEach(machineStatusAbnormal -> {
                if (!existNOs.contains(machineStatusAbnormal.getMachineNO())) {
                    existNOs.add(machineStatusAbnormal.getMachineNO());
                    result.add(machineStatusAbnormal);
                }
            });
            machineManagerResult.setAbnormales(result);
        }
        /**运维占用车辆*/
        if (machineStateData.getOccupy() == 1) {
            List<MachineStatus> occupy = machineManagerService.getByOccupy(accountUserToken, machineStateData.getAccountId(), mapType,
                    machineStateData.getRegionId());
            List<MachineStatus> result = new ArrayList<>();
            occupy.forEach(machineStatus -> {
                if (!existNOs.contains(machineStatus.getMachineNO())) {
                    existNOs.add(machineStatus.getMachineNO());
                    result.add(machineStatus);
                }
            });
            machineManagerResult.setOccupy(result);
        }
        /**流入流出车辆*/
        if (machineStateData.getStream() == 1) {
            List<MachineStatus> stream = machineManagerService.getByStream(accountUserToken, machineStateData.getAccountId(),
                    machineStateData.getRegionId(), mapType);
            List<MachineStatus> result = new ArrayList<>();
            stream.forEach(machineStatus -> {
                if (!existNOs.contains(machineStatus.getMachineNO())) {
                    existNOs.add(machineStatus.getMachineNO());
                    result.add(machineStatus);
                }
            });
            machineManagerResult.setStream(result);
        }
        /**无盈利车辆*/
        if (machineStateData.getNoIncome() == 1) {
            List<MachineStatusBorrow> noIncome = machineManagerService.getNoIncome(accountUserToken, machineStateData.getAccountId()
                    , mapType, machineStateData.getRegionId(), machineStateData.getCount());
            List<MachineStatusBorrow> result = new ArrayList<>();
            noIncome.forEach(machineStatus -> {
                if (!existNOs.contains(machineStatus.getMachineNO())) {
                    existNOs.add(machineStatus.getMachineNO());
                    result.add(machineStatus);
                }
            });
            machineManagerResult.setNotInCome(result);
        }
        /**扣押车辆*/
        if (machineStateData.getDetention() == 1) {
            List<MachineStatus> detention = machineManagerService.getByDetention(machineStateData.getAccountId(), mapType,
                    machineStateData.getRegionId());
            List<MachineStatus> result = new ArrayList<>();
            detention.forEach(machineStatus -> {
                if (!existNOs.contains(machineStatus.getMachineNO())) {
                    existNOs.add(machineStatus.getMachineNO());
                    result.add(machineStatus);
                }
            });
            machineManagerResult.setDetention(result);
        }
        /**回收车辆*/
        if (machineStateData.getStock() == 1) {
            List<MachineStatus> stock = machineManagerService.getByStock(machineStateData.getAccountId(), mapType,
                    machineStateData.getRegionId());
            List<MachineStatus> result = new ArrayList<>();
            stock.forEach(machineStatus -> {
                if (!existNOs.contains(machineStatus.getMachineNO())) {
                    existNOs.add(machineStatus.getMachineNO());
                    result.add(machineStatus);
                }
            });
            machineManagerResult.setStock(result);
        }
        return JsonResult.succ(machineManagerResult);
    }

    /**
     * 根据电量查询
     */
    @RequestMapping("/getByPower")
    public JsonResult<List<MachineStatus>> getByPower(String token, Integer accountId, Integer soc, Integer mapType,
                                 @RequestParam(value = "regionId", required = false) List<Integer> regionId
            , Integer startSoc, Integer endSoc) {
        AccountUser accountUserToken = tokenService.getAccount(token);
        Assert.notNull(accountId, "AccountUser.agentId.notNull");
        //删除用户，修改用户角色检测
        AccountUserBound accountUserBound = accountUserService.getBoundByUserId(accountUserToken.getAccountUserId());
        if (accountUserBound == null) {
            /**删除token*/
            redisService.del(token);
            throw new BaseException("AccountUser.notExist");
        } else {
            if (!accountUserBound.getSubRoleType().equals(accountUserToken.getSubRoleType())) {
                /**删除token*/
                redisService.del(token);
                throw new BaseException("System.login.need");
            }
            if (accountUserBound.getExpireDate() != null) {
                if (DateTimeUtil.isBeforeToday(accountUserBound.getExpireDate())) {
                    throw new BaseException("AccountUser.user.expire");
                }
            }
        }

        if (mapType == null) {
            mapType = SysConstant.GOOGLE;
        }

        if (soc == null) {
            soc = 30;
        }

        if (CollUtil.isEmpty(regionId)) {
            regionId = georeGionService.getByAccountUserId(accountUserToken.getAccountUserId());
        }

        List<MachineStatus> machineStatuses = machineManagerService.getByPower(accountUserToken, accountId, soc, mapType, regionId, startSoc, endSoc);

        return JsonResult.succ(machineStatuses);
    }

    /**
     * 闲置车辆查询
     */
    @RequestMapping("/getByUnuse")
    public JsonResult getByUnuse(String token, Integer accountId, @RequestParam(defaultValue = "12") Integer hours, Integer mapType,
                                 @RequestParam(value = "regionId", required = false) List<Integer> regionId
            , Integer start, Integer end) {
        Assert.notNull(accountId, "AccountUser.agentId.notNull");
        AccountUser accountUserToken = tokenService.getAccount(token);
        if (mapType == null) {
            mapType = SysConstant.GOOGLE;
        }
        if (CollectionUtils.isEmpty(regionId)) {
            regionId = georeGionService.getByAccountUserId(accountUserToken.getAccountUserId());
        }

        List<MachineStatusBorrow> machineStatusBorrows = machineManagerService.getByUnuse(accountUserToken, accountId, hours, mapType, regionId, start, end);

        return JsonResult.succ(machineStatusBorrows);
    }

    /**
     * 故障车辆
     */
    @RequestMapping("/getByFault")
    public JsonResult getByFault(String token, Integer accountId, Integer mapType,
                                 @RequestParam(value = "regionId", required = false) List<Integer> regionId) {
        AccountUser accountUserToken = tokenService.getAccount(token);
        Assert.notNull(accountId, "AccountUser.agentId.notNull");
        if (mapType == null) {
            mapType = SysConstant.GOOGLE;
        }

        if (CollUtil.isEmpty(regionId)) {
            regionId = georeGionService.getByAccountUserId(accountUserToken.getAccountUserId());
        }

        List<MachineStatusFault> machineStatusFaults = machineManagerService.getByFault(accountUserToken, accountId, mapType, null, regionId);
        return JsonResult.succ(machineStatusFaults);
    }

    /**
     * 异常车辆
     */
    @RequestMapping("/getByAbnormal")
    public JsonResult getByAbnormal(String token, Integer accountId, Integer abnormalType, Integer mapType,
                                    @RequestParam(value = "regionId", required = false) List<Integer> regionId,
                                    @RequestParam(value = "hours", required = false) Integer hours) {
        AccountUser accountUserToken = tokenService.getAccount(token);
        Assert.notNull(accountId, "AccountUser.agentId.notNull");
        if (mapType == null) {
            mapType = SysConstant.GOOGLE;
        }

        if (CollUtil.isEmpty(regionId)) {
            regionId = georeGionService.getByAccountUserId(accountUserToken.getAccountUserId());
        }

        List<MachineStatusAbnormal> machineStatusAbnormales = machineManagerService.getByAbnormal(accountUserToken, accountId, abnormalType, mapType, regionId, hours);

        return JsonResult.succ(machineStatusAbnormales);
    }

    /**
     * 运维占用车辆
     */
    @RequestMapping("/getByOccupy")
    public JsonResult getByOccupy(String token, Integer accountId, Integer mapType,
                                  @RequestParam(value = "regionId", required = false) List<Integer> regionId) {
        AccountUser accountUserToken = tokenService.getAccount(token);
        Assert.notNull(accountId, "AccountUser.agentId.notNull");
        if (mapType == null) {
            mapType = SysConstant.GOOGLE;
        }

        if (CollUtil.isEmpty(regionId)) {
            regionId = georeGionService.getByAccountUserId(accountUserToken.getAccountUserId());
        }

        List<MachineStatus> machineStatuses = machineManagerService.getByOccupy(accountUserToken, accountId, mapType, regionId);

        return JsonResult.succ(machineStatuses);
    }

    /**
     * 流动流出车辆
     */
    @RequestMapping("/getStream")
    public JsonResult getStream(String token, Integer accountId, Integer mapType,
                                @RequestParam(value = "regionId", required = false) List<Integer> regionId) {

        AccountUser accountUserToken = tokenService.getAccount(token);
        Assert.notNull(accountId, "AccountUser.agentId.notNull");
        if (mapType == null) {
            mapType = SysConstant.GOOGLE;
        }

        if (CollUtil.isEmpty(regionId)) {
            regionId = georeGionService.getByAccountUserId(accountUserToken.getAccountUserId());
        }

        List<MachineStatus> machineStatuss = machineManagerService.getByStream(accountUserToken, accountId, regionId, mapType);

        return JsonResult.succ(machineStatuss);
    }


    /**
     * 无盈利车辆
     */
    @RequestMapping("/getNoIncome")
    public JsonResult getNoIncome(String token, Integer accountId, Integer mapType, Integer count,
                                  @RequestParam(value = "regionId", required = false) List<Integer> regionId) {
        AccountUser accountUserToken = tokenService.getAccount(token);
        Assert.notNull(accountId, "AccountUser.agentId.notNull");
        if (mapType == null) {
            mapType = SysConstant.GOOGLE;
        }

        if (CollUtil.isEmpty(regionId)) {
            regionId = georeGionService.getByAccountUserId(accountUserToken.getAccountUserId());
        }

        List<MachineStatusBorrow> machineStatusBorrows = machineManagerService.getNoIncome(accountUserToken, accountId, mapType, regionId, count);

        return JsonResult.succ(machineStatusBorrows);
    }

    /**
     * 查询扣押车辆信息
     *
     * @param token
     * @param accountId
     * @param mapType
     * @param regionId
     * @return
     */
    @RequestMapping("/getByDetention")
    public JsonResult getByDetention(String token, Integer accountId, Integer mapType,
                                     @RequestParam(value = "regionId", required = false) List<Integer> regionId) {
        AccountUser accountUserToken = tokenService.getAccount(token);
        Assert.notNull(accountId, "AccountUser.agentId.notNull");
        if (mapType == null) {
            mapType = SysConstant.GOOGLE;
        }

        if (CollUtil.isEmpty(regionId)) {
            regionId = georeGionService.getByAccountUserId(accountUserToken.getAccountUserId());
        }

        List<MachineStatus> machineStatuses = machineManagerService.getByDetention(accountId, mapType, regionId);

        return JsonResult.succ(machineStatuses);
    }

    /**
     * 查询入库车辆信息
     *
     * @param token
     * @param accountId
     * @param mapType
     * @param regionId
     * @return
     */
    @RequestMapping("/getByStock")
    public JsonResult getByStock(String token, Integer accountId, Integer mapType,
                                 @RequestParam(value = "regionId", required = false) List<Integer> regionId) {
        AccountUser accountUserToken = tokenService.getAccount(token);
        Assert.notNull(accountId, "AccountUser.agentId.notNull");
        if (mapType == null) {
            mapType = SysConstant.GOOGLE;
        }

        if (CollUtil.isEmpty(regionId)) {
            regionId = georeGionService.getByAccountUserId(accountUserToken.getAccountUserId());
        }

        List<MachineStatus> machineStatuses = machineManagerService.getByStock(accountId, mapType, regionId);

        return JsonResult.succ(machineStatuses);
    }


    /**
     * 骑行中
     */
    @RequestMapping("/getByUseIng")
    public JsonResult getByUseIng(String token, Integer accountId, Integer mapType,
                                  @RequestParam(value = "regionId", required = false) List<Integer> regionId) {
        AccountUser accountUserToken = tokenService.getAccount(token);
        Assert.notNull(accountId, "AccountUser.agentId.notNull");
        if (mapType == null) {
            mapType = SysConstant.GOOGLE;
        }

        if (CollUtil.isEmpty(regionId)) {
            regionId = georeGionService.getByAccountUserId(accountUserToken.getAccountUserId());
        }

        List<MachineStatus> machineStatuses = machineManagerService.getByUseIng(accountUserToken, accountId, mapType, regionId);

        return JsonResult.succ(machineStatuses);
    }


    /**
     * 异常还车
     */
    @RequestMapping("/getAbnormalReturn")
    public JsonResult getAbnormalReturn(String token, Integer accountId, Integer mapType,
                                        @RequestParam(value = "regionId", required = false) List<Integer> regionId,
                                        Integer type) {
        AccountUser accountUserToken = tokenService.getAccount(token);
        Assert.notNull(accountId, "AccountUser.agentId.notNull");
        if (mapType == null) {
            mapType = SysConstant.GOOGLE;
        }

        if (CollUtil.isEmpty(regionId)) {
            regionId = georeGionService.getByAccountUserId(accountUserToken.getAccountUserId());
        }

        List<MachineStatus> machineStatuses = machineManagerService.getAbnormalReturn(accountUserToken, accountId, mapType, regionId, type);

        return JsonResult.succ(machineStatuses);
    }

    /**
     * 手动上报定位
     * 挪车、调度时，也会调用此方法
     *
     * @param userCodeS
     * @param lon
     * @param lat
     * @param lonPeople
     * @param latPeople
     * @param mapType
     * @return
     */
    @RequestMapping("/pushPost")
    @OperateLog(module = ModuleEnum.MACHINEMANAGER, methods = MethodEnum.MACHINEMANAGER_PUSHPOST)
    public JsonResult pushPost(String userCodeS, Double lon, Double lat,
                               Double lonPeople, Double latPeople,
                               Integer mapType) {
        Assert.hasLength(userCodeS, "Machine.userCode.notNull");
        Assert.notNull(lon, "System.lon.notNull");
        Assert.notNull(lat, "System.lat.notNull");
        Assert.notNull(lonPeople, "");
        Assert.notNull(latPeople, "AccountUser.agentId.notNull");

        if (mapType == null) {
            mapType = SysConstant.GOOGLE;
        }

        machineManagerService.pushPost(userCodeS, lon, lat, lonPeople, latPeople, mapType);

        return JsonResult.succ();
    }

    /**
     * 自定义标签车辆
     */
    @RequestMapping("/getByTag")
    public JsonResult getByTag(String token, Integer accountId, Integer mapType, @RequestParam(value = "tagIds", required = false) List<Integer> tagIds,
                               @RequestParam(value = "regionId", required = false) List<Integer> regionId) {
        AccountUser accountUserToken = tokenService.getAccount(token);
        Assert.notNull(accountId, "AccountUser.agentId.notNull");
        if (mapType == null) {
            mapType = SysConstant.GOOGLE;
        }

        if (CollUtil.isEmpty(regionId)) {
            regionId = georeGionService.getByAccountUserId(accountUserToken.getAccountUserId());
        }

        List<MachineStatusBorrow> byTag = machineManagerService.getByTag(accountUserToken, accountId, mapType, regionId, tagIds);
        return JsonResult.succ(byTag);
    }


    /**
     * 无定位
     */
    @RequestMapping("/getLongTermNonPos")
    public JsonResult<List<MachineStatus>> getLongTermNonPos(@NotNull(message = "AccountUser.agentId.notNull") Integer accountId,
                                                             @RequestParam(defaultValue = "12") Integer hours,
                                                             @RequestParam(defaultValue = "2") Integer mapType,
                                                             @RequestParam(required = false) List<Integer> regionId) {
        List<MachineStatus> machineStatuses = machineManagerService.getLongTermNonPos(accountId, regionId, mapType, hours);
        return JsonResult.succ(machineStatuses);
    }

    /**
     * 长时订单
     */
    @RequestMapping("/getLongOrder")
    public JsonResult<List<MachineStatus>> getLongOrder(@NotNull(message = "AccountUser.agentId.notNull") Integer accountId,
                                                             @RequestParam(defaultValue = "1") Integer hours,
                                                             @RequestParam(defaultValue = "2") Integer mapType,
                                                             @RequestParam(required = false) List<Integer> regionId) {
        List<MachineStatus> machineStatuses = machineManagerService.getLongOrder(accountId, regionId, mapType, hours);
        return JsonResult.succ(machineStatuses);
    }


    /**
     * 无订单
     * @param accountId 区域id
     * @param hours     小时
     * @param mapType   地图类型
     * @param regionId  分区id
     * @return  Result<List<MachineStatus>>
     */
    @GetMapping("/getNoOrder")
    public Result<List<MachineStatus>> getNoOrder(@NotNull(message = "AccountUser.agentId.notNull") Integer accountId,
                                                  @RequestParam(defaultValue = "1")Integer hours,
                                                  @RequestParam(defaultValue = "2") Integer mapType,
                                                  @RequestParam(required = false) String regionId){
        List<MachineStatus> machineStatuses = machineManagerService.getNoOrder(accountId, hours, mapType, regionId);
        return Result.success(machineStatuses);
    }


    /**
     * 运营地图监控
     * @param dto OperatingMapMainDTO
     * @return  List<OperatingMonitorMainVO>
     */
    @PostMapping("/operatingMapMonitoringV2")
    public Result<List<OperatingMonitorMainVO>> operatingMapMonitoringV2(@RequestBody OperatingMapMainDTO dto) {
        if (Objects.isNull(dto.getAccountId())){
            return Result.error("请选择区域");
        }
        List<OperatingMonitorMainVO> operatingMonitorMainVOS = machineApi.operatingMapMonitoringV2(dto);
        return Result.success(operatingMonitorMainVOS);
    }
}